﻿using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using Channelvn.Cached.Common;
using Channelvn.MemcachedProviders.Cache;

namespace Channelvn.Cached
{
    public class CacheController
    {
        private const long _DefaultCacheExpire = 2592000; // in seconds (30 days)
        public static string ParentCategory
        {
            get
            {
                string parentCat = Lib.QueryString.ParentZone;

                if (string.IsNullOrEmpty(parentCat) || parentCat == "0")
                {
                    parentCat = Lib.QueryString.ZoneID.ToString();
                }

                if (string.IsNullOrEmpty(parentCat))
                {
                    string cacheName = string.Format("Memcached_ParentCategory_{0}", parentCat);

                    parentCat = (HttpContext.Current.Cache[cacheName] == null || string.IsNullOrEmpty(HttpContext.Current.Cache[cacheName].ToString()) ? "" : HttpContext.Current.Cache[cacheName].ToString());

                    if (string.IsNullOrEmpty(parentCat))
                    {
                        parentCat = Lib.GetParentCategoryByCategoryId(Lib.QueryString.ZoneID);
                    }
                }

                return parentCat;
            }
        }

        public static bool IsAllowDistributedCached
        {
            get
            {
                return (ConfigurationManager.AppSettings["AllowDistCache"] == "1");
            }
        }

        public static bool IsCacheExists(string key)
        {
            if (IsAllowDistributedCached)
            {
                return DistCached.GetInstance(ParentCategory).Get(key) != null;
            }
            else
            {
                return false;
            }
        }
        public static bool IsCacheExists(string parentCategory, string key)
        {
            if (IsAllowDistributedCached)
            {
                return DistCached.GetInstance(parentCategory).Get(key) != null;
            }
            else
            {
                return false;
            }
        }

        public static void Add(string key, object value, long timeExpire)
        {
            if (IsAllowDistributedCached)
            {
                string lastUpdateKey = string.Format(Constants.CACHE_NAME_LAST_UPDATE, key);
                if (timeExpire > 0)
                {
                    DistCached.GetInstance(ParentCategory).Add(key, value, timeExpire * 1000);
                    DistCached.GetInstance(ParentCategory).Add(lastUpdateKey, DateTime.Now.ToString(), timeExpire * 1000);
                }
                else
                {
                    DistCached.GetInstance(ParentCategory).Add(key, value, _DefaultCacheExpire * 1000);
                    DistCached.GetInstance(ParentCategory).Add(lastUpdateKey, DateTime.Now.ToString(), _DefaultCacheExpire * 1000);
                }
            }
        }
        public static void Add(string parentCategory, string key, object value, long timeExpire)
        {
            if (IsAllowDistributedCached)
            {
                string lastUpdateKey = string.Format(Constants.CACHE_NAME_LAST_UPDATE, key);
                if (timeExpire > 0)
                {
                    DistCached.GetInstance(parentCategory).Add(key, value, timeExpire * 1000);
                    DistCached.GetInstance(parentCategory).Add(lastUpdateKey, DateTime.Now.ToString(), timeExpire * 1000);
                }
                else
                {
                    DistCached.GetInstance(parentCategory).Add(key, value, _DefaultCacheExpire * 1000);
                    DistCached.GetInstance(parentCategory).Add(lastUpdateKey, DateTime.Now.ToString(), _DefaultCacheExpire * 1000);
                }
            }
        }

        public static object GetCache(string key)
        {
            if (IsAllowDistributedCached)
            {
                //Lib.WriteLogToFile(DistCached.GetProvidersState());
                //DateTime start = DateTime.Now;
                object data = DistCached.GetInstance(ParentCategory).Get(key);
                //DateTime end = DateTime.Now;
                //Lib.WriteLogToFile(key + "(" + (end.Ticks - start.Ticks).ToString() + "): " + end.ToString("HH:mm:ss.FFFFFFF") + "     " + start.ToString("HH:mm:ss.FFFFFFF"));
                return data;
            }
            else
            {
                return null;
            }
        }
        public static object GetCache(string parentCategory, string key)
        {
            if (IsAllowDistributedCached)
            {
                //Lib.WriteLogToFile(DistCached.GetProvidersState());
                //DateTime start = DateTime.Now;
                object data = DistCached.GetInstance(parentCategory).Get(key);
                //DateTime end = DateTime.Now;
                //Lib.WriteLogToFile(key + "(" + (end.Ticks - start.Ticks).ToString() + "): " + end.ToString("HH:mm:ss.FFFFFFF") + "     " + start.ToString("HH:mm:ss.FFFFFFF"));
                return data;
            }
            else
            {
                return null;
            }
        }

        public static T Get<T>(string key)
        {
            if (IsAllowDistributedCached)
            {
                if (IsCacheExists(ParentCategory, key))
                {
                    //DateTime start = DateTime.Now;
                    T data = DistCached.GetInstance(ParentCategory).Get<T>(key);
                    //DateTime end = DateTime.Now;
                    //Lib.WriteLogToFile(key + "(" + (end.Ticks - start.Ticks).ToString() + "): " + end.ToString("HH:mm:ss.FFFFFFF") + "     " + start.ToString("HH:mm:ss.FFFFFFF"));
                    return data;
                }
                else
                {
                    return default(T);
                }
            }
            else
            {
                return default(T);
            }
        }
        public static T Get<T>(string parentCategory, string key)
        {
            if (IsAllowDistributedCached)
            {
                if (IsCacheExists(parentCategory, key))
                {
                    //DateTime start = DateTime.Now;
                    T data = DistCached.GetInstance(parentCategory).Get<T>(key);
                    //DateTime end = DateTime.Now;
                    //Lib.WriteLogToFile(key + "(" + (end.Ticks - start.Ticks).ToString() + "): " + end.ToString("HH:mm:ss.FFFFFFF") + "     " + start.ToString("HH:mm:ss.FFFFFFF"));
                    return data;
                }
                else
                {
                    return default(T);
                }
            }
            else
            {
                return default(T);
            }
        }

        public static void Remove(string key)
        {
            if (IsAllowDistributedCached)
            {
                string lastUpdateKey = string.Format(Constants.CACHE_NAME_LAST_UPDATE, key);
                DistCached.GetInstance(ParentCategory).Remove(key);
                DistCached.GetInstance(ParentCategory).Remove(lastUpdateKey);
            }
        }
        public static void Remove(string parentCategory, string key)
        {
            if (IsAllowDistributedCached)
            {
                string lastUpdateKey = string.Format(Constants.CACHE_NAME_LAST_UPDATE, key);
                DistCached.GetInstance(parentCategory).Remove(key);
                DistCached.GetInstance(parentCategory).Remove(lastUpdateKey);
            }
        }


        public static void RemoveAll()
        {
            if (IsAllowDistributedCached)
            {
                DistCached.GetInstance(ParentCategory).RemoveAll();
            }
        }
        public static void RemoveAll(string parentCategory)
        {
            if (IsAllowDistributedCached)
            {
                DistCached.GetInstance(parentCategory).RemoveAll();
            }
        }

        /// <summary>
        /// Lấy thời gian cập nhật cache lần cuối
        /// </summary>
        /// <param name="key">Cache name</param>
        /// <returns>Nếu chưa có cache thì trả về DateTime.MinValue</returns>
        public static DateTime GetLastUpdateCache(string key)
        {
            if (IsAllowDistributedCached)
            {
                string lastUpdateKey = string.Format(Constants.CACHE_NAME_LAST_UPDATE, key);
                try
                {
                    object lastUpdate = DistCached.GetInstance(ParentCategory).Get(lastUpdateKey);
                    if (null != lastUpdate)
                    {
                        return Convert.ToDateTime(lastUpdate);
                    }
                    else
                    {
                        return DateTime.MinValue;
                    }
                }
                catch
                {
                    return DateTime.MinValue;
                }
            }
            else
            {
                return DateTime.MinValue;
            }
        }
        /// <summary>
        /// Lấy thời gian cập nhật cache lần cuối
        /// </summary>
        /// <param name="parentCategory"></param>
        /// <param name="key"></param>
        /// <returns>Nếu chưa có cache thì trả về DateTime.MinValue</returns>
        public static DateTime GetLastUpdateCache(string parentCategory, string key)
        {
            if (IsAllowDistributedCached)
            {
                string lastUpdateKey = string.Format(Constants.CACHE_NAME_LAST_UPDATE, key);
                try
                {
                    object lastUpdate = DistCached.GetInstance(parentCategory).Get(lastUpdateKey);
                    if (null != lastUpdate)
                    {
                        return Convert.ToDateTime(lastUpdate);
                    }
                    else
                    {
                        return DateTime.MinValue;
                    }
                }
                catch
                {
                    return DateTime.MinValue;
                }
            }
            else
            {
                return DateTime.MinValue;
            }
        }
    }
}
